#ifndef USB_H_
#define USB_H_

#include "stdint.h"

//#define uint8_t		uint8
//#define uint16_t	uint16
//#define uint32_t	uint32

#define __u8 uint8_t
#define __u16 uint16_t
#define __u32 uint32_t

/* Descriptor Types */
#define USB_DEVICE_DESCRIPTOR_TYPE              1
#define USB_CONFIGURATION_DESCRIPTOR_TYPE       2
#define USB_STRING_DESCRIPTOR_TYPE              3
#define USB_INTERFACE_DESCRIPTRO_TYPE           4
#define USB_ENDPOINT_DESCRIPTOR_TYPE            5

#define USB_CONFIGURATION_DESC_SIZE             (9)
#define USB_DEVICE_DESC_SIZE                    (18)
#define USB_INTERFACE_DESC_SIZE                 (9)
#define USB_ENDPOINT_DESC_SIZE                  (7)

#define USB_ENDPOINT_IN(x)                      (0x80 | (x))
#define USB_ENDPOINT_OUT(x)                     (0x00 | (x))

#define USB_ENDPOINT_TYPE_MASK                  0x03
#define USB_ENDPOINT_TYPE_CONTROL               0x00
#define USB_ENDPOINT_TYPE_ISOCHRONOUS           0x01
#define USB_ENDPOINT_TYPE_BULK                  0x02
#define USB_ENDPOINT_TYPE_INTERRUPT             0x03
#define USB_ENDPOINT_SYNC_MASK                  0x0C
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION    0x00
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS          0x04
#define USB_ENDPOINT_SYNC_ADAPTIVE              0x08
#define USB_ENDPOINT_SYNC_SYNCHRONOUS           0x0C
#define USB_ENDPOINT_USAGE_MASK                 0x30
#define USB_ENDPOINT_USAGE_DATA                 0x00
#define USB_ENDPOINT_USAGE_FEEDBACK             0x10
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK    0x20
#define USB_ENDPOINT_USAGE_RESERVED             0x30

#define USB_DEVICE_CLASS_VENDOR_SPECIFIC        (0xFF)

/* CDC */
#define ACM_REQUEST_SET_LINE_CODING             0x20
#define ACM_REQUEST_GET_LINE_CODING             0x21
#define ACM_REQUEST_SET_CONTROL_LINE_STATE      0x22

#define USB_CLASS_COMM                          0x02
#define USB_CDC_SUBCLASS_ACM                    0x02
#define USB_CLASS_DATA                          0x0A

#define USB_CDC_ACM_NO_CLASS_SPECIFIC           0
#define USB_CDC_ACM_PROTO_AT_V25TER             1
#define USB_CDC_ACM_PROTO_AT_PCCA101            2
#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE       3
#define USB_CDC_ACM_PROTO_AT_GSM                4
#define USB_CDC_ACM_PROTO_AT_3G                 5
#define USB_CDC_ACM_PROTO_AT_CDMA               6
#define USB_CDC_ACM_PROTO_VENDOR                0xff

#define CONFIG_DESC_NUM_INTERFACES              (2)
#define NUM_ENDPOINTS                           (2)
#define CDC_ACM_DEFAULT_BAUDRATE                115200
#define CDC_ACM_DEFAULT_STOPBITS                1
#define CDC_ACM_DEFAULT_PARITY                  0
#define CDC_ACM_DEFAULT_DATABITS                8

#define HEADER_FUNC_DEC_LENGTH                  0x05
#define CALL_MANAGEMENT_FUNC_DESC_LENGTH        0x05
#define ACM_FUNC_DESC_LENGTH                    0x04
#define UNION_FUNC_DESC_LENGTH                  0x05

#define DESC_TYPE_CS_INTERFACE                  0x24
#define DESC_TYPE_CS_ENDPOINT                   0x25


#define DESC_SUBTYPE_CS_HEADER_FUNC             0x00
#define DESC_SUBTYPE_CS_CALL_MAN                0x01
#define DESC_SUBTYPE_CS_ABST_CNTRL              0x02
#define DESC_SUBTYPE_CS_UNION_FUNC              0x06

#define CDC_ENDPOINTS                           3

#define REG_TYPE_STANDARD                         0x00
#define REQ_TYPE_DEVICE                        0x00
#define REQ_TYPE_INTERFACE                     0x01
#define REQ_TYPE_ENDPOINT                      0x02
#define REQ_TYPE_IN                            0x80
#define REQ_TYPE_OUT                           0x00
#define REQ_TYPE_CLASS                         0x20
#define REQ_TYPE_VENDOR                        0x40
#define REG_TYPE_MASK                          0x60

#define CDC_REQ_NOTIF   (REQ_TYPE_IN | REQ_TYPE_CLASS | REQ_TYPE_INTERFACE)
#define CDC_REQ_OUT     (REQ_TYPE_OUT | REQ_TYPE_CLASS | REQ_TYPE_INTERFACE)
#define CDC_REQ_IN      (REQ_TYPE_IN | REQ_TYPE_CLASS | REQ_TYPE_INTERFACE)

#define CDC_NOTIF_NETWORK_CONNECTION            0x00
#define CDC_NOTIF_RESPONSE_AVAILABLE            0x01
#define CDC_NOTIF_AUX_JACK_HOOK_STATE           0x08
#define CDC_NOTIF_RING_DETECT                   0x09
#define CDC_NOTIF_SERIAL_STATE                  0x20
#define CDC_NOTIF_CALL_STATE_CHANGE             0x28
#define CDC_NOTIF_LINE_STATE_CHANGE             0x29
#define CDC_NOTIF_CONNECTION_SPEED_CHANGE       0x2a

/* Descriptor Struct */

#define DescriptorHeader \
        __u8 bLength;        \
        __u8 bDescriptorType

/* Device Descriptor */
typedef struct {
         DescriptorHeader;
         __u16 bcdUSB;          /* USB specification revision number in BCD */
         __u8 bDeviceClass;     /* USB class for entire device */
         __u8 bDeviceSubClass;  /* USB subclass information for entire device */
         __u8 bDeviceProtocol;  /* USB protocol information for entire device */
         __u8 bMaxPacketSize0;  /* Max packet size for endpoint zero */
         __u16 idVendor;        /* USB vendor ID */
         __u16 idProduct;       /* USB product ID */
         __u16 bcdDevice;       /* vendor assigned device release number */
         __u8 iManufacturer;    /* index of manufacturer string */
         __u8 iProduct;         /* index of string that describes product */
         __u8 iSerialNumber;    /* index of string containing device serial number */
         __u8 bNumConfigurations; /* number fo configurations */
} __attribute__ ((packed)) device_desc_t;

/* Configuration Descriptor */
typedef struct {
         DescriptorHeader;
         __u16 wTotalLength;    /* total # of bytes returned in the cfg buf 4 this cfg */
         __u8 bNumInterfaces;   /* number of interfaces in this cfg */
         __u8 bConfigurationValue;/* used to uniquely ID this cfg */
         __u8 iConfiguration;   /* index of string describing cfg*/
         __u8 bmAttributes;     /* bitmap of attributes for ths cfg */
         __u8 MaxPower;         /* power draw in 2ma units */
} __attribute__ ((packed)) config_desc_t;

/* bmAttributes */
#define USB_CONFIG_REMOTEWAKE   0x20
#define USB_CONFIG_SELFPOWERED  0x40
#define USB_CONFIG_BUSPOWERED   0x80

/*
 * MaxPower
 * convert mA to descriptor units of A for MaxPower
 */
 #define USB_POWER( x)  ((x)>>1)

/* Interface Descriptor */

typedef struct {
         DescriptorHeader;
         __u8  bInterfaceNumber;   /* Index uniquely identfying this interface */
         __u8  bAlternateSetting;  /* ids an alternate setting for this interface */
         __u8  bNumEndpoints;      /* number of endpoints in this interface */
         __u8  bInterfaceClass;    /* USB class info applying to this interface */
         __u8  bInterfaceSubClass; /* USB subclass info applying to this interface */
         __u8  bInterfaceProtocol; /* USB protocol info applying to this interface */
         __u8  iInterface;         /* index of string describing interface */
} __attribute__ ((packed)) intf_desc_t;

/* String Descriptor */
#define USB_LANGID_US_L 0x09
#define USB_LANGID_US_H 0x04

typedef struct {
         DescriptorHeader;
         __u16 bString[1];      /* unicode string .. actaully 'n' __u16s */
} __attribute__ ((packed)) string_desc_t;

/* Endpoint  Descriptor */
typedef struct {
         DescriptorHeader;
         __u8 bEndpointAddress; /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
         __u8 bmAttributes;     /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
         __u16 wMaxPacketSize;  /* data payload size for this ep in this cfg */
         __u8 bInterval;        /* polling interval for this ep in this cfg */
} __attribute__ ((packed)) ep_desc_t;

#define ACM_REQUEST_SET_LINE_CODING          0x20
#define ACM_REQUEST_GET_LINE_CODING          0x21
#define ACM_REQUEST_SET_CONTROL_LINE_STATE   0x22

#define USB_CDC_HEADER                             0x00
#define USB_CDC_CALLMANAGEMENT                     0x01

#define USB_CDC_ABSTRACTCONTROLMANAGEMENT          0x02
#define USB_CDC_UNION                              0x06

#define USB_CDC_INTERFACE                          0x24
#define USB_CDC_ENDPOINT                           0x25

#define USB_CDC_CDC1_10                            0x0110

typedef struct {
        DescriptorHeader;
        __u8 bDescriptorSubtype;
        __u16 bcdCDC;
} __attribute__ ((packed)) cdc_header_desc_t;

#define USB_CDC_SELFCALLMANAGEMENT      (1 << 0)
#define USB_CDC_DATACALLMANAGEMENT      (1 << 1)
typedef struct {
        DescriptorHeader;
        __u8 bDescriptorSubtype;
        __u8 bmCapabilities;
        __u8 bDataInterface;
} __attribute__ ((packed)) cdc_callm_desc_t;

#define USB_CDC_COMMFEATURE          (1 << 0)
#define USB_CDC_LINE                 (1 << 1)
#define USB_CDC_SENDBREAK            (1 << 2)
#define USB_CDC_NETWORKCONNECTION    (1 << 3)
typedef struct {
        DescriptorHeader;
        __u8 bDescriptorSubtype;

        __u8 bmCapabilities;
} __attribute__ ((packed)) cdc_acm_desc_t;

typedef struct {
        DescriptorHeader;
        __u8 bDescriptorSubtype;
        __u8 bMasterInterface;
        __u8 bSlaveInterface0;
} __attribute__ ((packed)) cdc_union_desc_t;

#define USB_OUT 0
#define USB_IN  1
#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))

/* bmAttributes: */
#define USB_EP_CNTRL            0
#define USB_EP_ISOCHRONOUS      1
#define USB_EP_BULK             2
#define USB_EP_INT              3

/*
 * USB Device Requests
 * Refer to chapter 9.3 in the USB specification v2.0
 */
typedef struct {
        __u8 bmRequestType;
        __u8 bRequest;
        __u16 wValue;
        __u16 wIndex;
        __u16 wLength;
} __attribute__ ((packed)) device_req_t;

/*
 * bmRequestType
 * [7]   : Data transfer direction, 0 = Host to device, 1 = Device to host
 * [6:5] : Type
 * [4:0] : Recipient
 * Refer to Table 9-3 Fromat of Setup Data in the USB specification v2.0
 */
#define USB_RECIPIENT_DEVICE    0
#define USB_RECIPIENT_INTERFACE 1
#define USB_RECIPIENT_ENDPOINT  2
#define USB_RECIPIENT_OTHER     3

/*
 * bRequest
 * Refer to Table 9-4 Standard Device Requests in the USB specification v2.0
 */
#define USB_REQ_GET_STATUS              0
#define USB_REQ_CLEAR_FEATURE           1
#define USB_REQ_RESERVED_1              2
#define USB_REQ_SET_FEATURE             3
#define USB_REQ_RESERVED_2              4
#define USB_REQ_SET_ADDRESS             5
#define USB_REQ_GET_DESCRIPTOR          6
#define USB_REQ_SET_DESCRIPTOR          7
#define USB_REQ_GET_CONFIGURATION       8
#define USB_REQ_SET_CONFIGURATION       9
#define USB_REQ_GET_INTERFACE           10
#define USB_REQ_SET_INTERFACE           11
#define USB_REQ_SYNCH_FRAME             12
#define USB_REQ_MAX                     12

/*
 * Feature Selector
 * Refer to Table 9-6 Standard Feature Selectors in the USB specification v2.0
 */
#define USB_ENDPOINT_HALT       0
#define USB_DEV_REMOTE_WAKEUP   1
#define USB_TEST_MODE           2

#define USB_DESC_DEVICE_SIZE    sizeof(device_desc_t)
#define USB_DESC_CONFIG_SIZE    sizeof(config_desc_t)
#define USB_DESC_STRING_SIZE    sizeof(string_desc_t)
#define USB_DESC_INTERFACE_SIZE sizeof(intf_desc_t)
#define USB_DESC_ENDPOINT_SIZE  sizeof(ep_desc_t)


#include "udc.h"

typedef struct {
        uint8_t Device;
        uint8_t Interface;
        uint8_t Endpoint[MAX_ENDPOINT];
} __attribute__ ((packed)) get_status_t;

typedef struct
{
        uint8_t AlternateSetting;
} __attribute__ ((packed)) get_intf_t;

typedef struct {
        const __u8 * dev_desc;
        const __u8 * cfg_desc;
        const __u8 * str_desc[4];
        const __u8 dev_desc_len;
        const __u8 cfg_desc_len;
        const __u8 str_desc_len[4];
}usb_setup_t;

typedef struct _cdc_acm_linecode_t
{
		__u32 dte_rate;           // Data terminal rate, in bits per second

        /* Stop Bits
        0  -  1  Stop Bit
        1  -  1.5 Stop Bits
        2  -  2  Stop Bits
        */

		__u8 char_fmt;

        /*  Parity
        0 - None
        1 - Odd
        2 - Even
        3 - Mark
        4 - Space
        */

		__u8 parity_type;

        /* Data Bits

        5,6,7,8 Data Bits
        */

		__u8 data_bits;
		__u8 res1;
}cdc_acm_linecode_t;
#define LINECODE_SIZE			(7)

#define USB_IDLE                0xFF
#define USB_RESET				0xFE
#define USB_CTRL_SETUP          0x00
#define USB_CTRL_IN_TOKEN       0x01
#define USB_CTRL_IN_OK          0x02
#define USB_CTRL_OUT            0x03
#define USB_CTRL_OUT_OK         0x04

#endif /* USB_H_ */
